﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace VirtualKeyboards
{
    /// <summary>
    /// 鼠标键盘控制器
    /// </summary>
    public class MouseEvent
    {
        public string type { get; set; }
        public int buttonType { get; set; }
        public int x { get; set; }
        public int y { get; set; }
        public int wheelDelta { get; set; }
    }
    public class KeyEvent
    {
        public string type { get; set; }
        public string keyName { get; set; }
        public int keyCode { get; set; }
    }
    public class EventHelper
    {
        [DllImport("user32.dll")]
        private static extern bool SetCursorPos(int X, int Y);
        [DllImport("user32.dll")]
        private static extern void mouse_event(MouseEventFlag flags, int dx, int dy, int dwData, IntPtr dwExtraInfo);
        [Flags]
        enum MouseEventFlag : uint
        {
            Move = 0x0001, // 移动鼠标
            LeftDown = 0x0002,// 模拟鼠标左键按下
            LeftUp = 0x0004,//模拟鼠标左键抬起
            RightDown = 0x0008,//模拟鼠标右键按下
            RightUp = 0x0010,// 模拟鼠标右键抬起
            MiddleDown = 0x0020,//模拟鼠标中键按下
            MiddleUp = 0x0040,//模拟鼠标中键抬起
            XDown = 0x0080,
            XUp = 0x0100,
            Wheel = 0x0800,//滚轮
            VirtualDesk = 0x4000,
            Absolute = 0x8000//标示是否采用绝对坐标
        }

        /// <summary>
        /// 合成一次击键事件
        /// </summary>
        /// <param name="bVk">定义一个虚拟键码。键码值必须在1～254之间</param>
        /// <param name="bScan">定义该键的硬件扫描码</param>
        /// <param name="dwFlags">定义函数操作的各个方面的一个标志位集。应用程序可使用如下一些预定义常数的组合设置标志位</param>
        /// <param name="dwExtraInfo">定义与击键相关的附加的32位值</param>
        [DllImport("user32.dll", EntryPoint = "keybd_event", SetLastError = true)]
        public static extern void keybd_event(int bVk, byte bScan, uint dwFlags, uint dwExtraInfo);

        [DllImport("user32.dll")]//拖动无窗体的控件
        public static extern bool ReleaseCapture();
        [DllImport("user32.dll")]
        public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
        public const int WM_SYSCOMMAND = 0x0112;
        public const int SC_MOVE = 0xF010;
        public const int HTCAPTION = 0x0002;

        static public void MouseEvent(MouseEvent e)
        {
            switch (e.type)
            {
                case "mousemove":
                    SetCursorPos(e.x, e.y);
                    break;
                case "mousedown":
                    SetCursorPos(e.x, e.y);
                    if (e.buttonType == 0)
                        mouse_event(MouseEventFlag.LeftDown, 0, 0, 0, IntPtr.Zero);
                    if (e.buttonType == 1)
                        mouse_event(MouseEventFlag.MiddleDown, 0, 0, 0, IntPtr.Zero);
                    if (e.buttonType == 2)
                        mouse_event(MouseEventFlag.RightDown, 0, 0, 0, IntPtr.Zero);
                    break;
                case "mouseup":
                    SetCursorPos(e.x, e.y);
                    if (e.buttonType == 0)
                        mouse_event(MouseEventFlag.LeftUp, 0, 0, 0, IntPtr.Zero);
                    if (e.buttonType == 1)
                        mouse_event(MouseEventFlag.MiddleUp, 0, 0, 0, IntPtr.Zero);
                    if (e.buttonType == 2)
                        mouse_event(MouseEventFlag.RightUp, 0, 0, 0, IntPtr.Zero);
                    break;
                case "mousewheel":
                    SetCursorPos(e.x, e.y);
                    mouse_event(MouseEventFlag.Wheel, 0, 0, e.wheelDelta, IntPtr.Zero);
                    break;
            }
        }
        static public void KeyEvent(KeyEvent e)
        {
            keybd_event(e.keyCode, 0, 0, 0);
        }
        static public void key_down(Keys keyCode)
        {
            keybd_event((byte)keyCode, 0, 0, 0);
        }
        static public void key_up(Keys keyCode)
        {
            keybd_event((byte)keyCode, 0, 2, 0);
        }
        static public void SendKeyMessage(string keyStr)
        {
            SendKeys.SendWait(keyStr);
        }

        static public int getWinWidth()
        {
            return Screen.PrimaryScreen.Bounds.Width;
        }

        static public int getWinHeight()
        {
            return Screen.PrimaryScreen.Bounds.Height;
        }
    }
}
